<template>
  <div v-if="list.length>=1" class="image_preview" @touchstart="mainTouchStart" @touchmove="mainTouchMove"
       @touchend="mainTouchEnd">
    <div class="image_preview_index">{{ index + 1 }}/{{ list.length }}</div>
    <div class="image_preview_main" ref="preview_main">
      <div class="image_preview_child" v-for="(item,index) in list" :key="index" :style="{left:index*100+'%'}">
        <div class="image_preview_img_box" ref="childBox">
          <img class="image_preview_img" :src="item.url" @load="imgLoad($event,index)">
        </div>
      </div>
    </div>
    <div class="loading" v-show="!list[index].load">
      <div class="loading_child"></div>
    </div>
  </div>
</template>

<script>
// eslint-disable-next-line no-unreachable
export default {
  name: "imagePreview",
  props: {
    current: {
      type: Number,
      default: 0
    },
    urls: {
      type: Array,
      default() {
        return []
      }
    }
  },
  data: () => {
    return {
      index: 0,
      list: [],
      windowWidth: 0,
      mainStartTime: 0,
      mainEndTime: 0,
      mainStartX: 0,
      mainStartY: 0,
      mainMoveX: 0,
      mainMoveY: 0,
      moveDistanceLeft: 0,
      mainLeft: 0,
      touchMoveEdge: 0,
      maxMultiple: 3,//最大倍数
      minMultiple: 0.7,//最小倍数
      isBothHands: false,
      isMove: false
    }
  },
  created() {
    this.windowWidth = window.screen.width;
    this.list = this.urls;
    this.index = this.current;
    // for (let i = 0; i < this.list.length; i++) {
    //   this.list[i].color = this.randomColor();
    // }
  },
  methods: {
    // 随机分配背景色
    randomColor(type = false) {
      const R = Math.floor(Math.random() * 256)
      const G = Math.floor(Math.random() * 256)
      const B = Math.floor(Math.random() * 256)
      const A = Math.random()
      if (type) {
        return `rgba(${R},${G},${B},${A})`
      }
      return `rgb(${R},${G},${B})`
    },
    imgLoad(e, index) {
      if (this.list.length == 0) return;
      this.list[index].load = true;
    },
    mainTouchStart(e) {
      e.preventDefault();
      this.moveDistanceLeft = 0;
      this.mainStartTime = new Date().getTime();
      const touches = e.touches;
      this.mainStartX = touches[0].clientX;
      this.mainStartY = touches[0].clientY;
      const domStyle = this.$refs.preview_main.style;
      let left = domStyle.getPropertyValue('--left');
      domStyle.setProperty('--duration', 0);
      let childStyle = this.$refs.childBox[this.index].style;
      childStyle.setProperty("--duration", 0);
      this.mainLeft = parseFloat(left) || 0;
      this.isMove = false;
      if (touches.length >= 2) {
        this.touchMoveEdge = 0;
        this.isBothHands = true;
      } else {
        this.isBothHands = false;
      }
    },
    mainTouchMove(e) {
      this.isMove = true;
      const domStyle = this.$refs.preview_main.style;
      const touches = e.touches;
      this.mainMoveX = touches[0].clientX;
      this.mainMoveY = touches[0].clientY;
      if (touches.length >= 2) {
        let x1 = touches[1].clientX;
        let y1 = touches[1].clientY;
        this.touchMoveEdge = this.getLength(this.mainMoveX, this.mainMoveY, x1, y1);
        return;
      }
      if (this.isBothHands) return;
      let scale = this.list[this.index].scale;
      const childStyle = this.$refs.childBox[this.index].style;
      if (scale != 1) {
        // 执行上下左右滑动处理
        this.leftOrRightMove(childStyle, domStyle);
        if (!this.computedMax()) return;
        this.topOrDownMove(childStyle);
        return;
      }
      // 长图处理
      if (this.computedMax()) {
        this.topOrDownMove(childStyle);
        if (Math.abs(this.mainMoveX - this.mainStartX) >= 50 && this.mainStartX > this.mainMoveX) {
          domStyle.setProperty('--left', this.mainLeft + this.mainMoveX - this.mainStartX + 50);
        } else if (Math.abs(this.mainMoveX - this.mainStartX) >= 50 && this.mainStartX < this.mainMoveX) {
          domStyle.setProperty('--left', this.mainLeft + this.mainMoveX - this.mainStartX - 50);
        }
        return;
      }
      domStyle.setProperty('--left', this.mainLeft + this.mainMoveX - this.mainStartX);
    },
    mainTouchEnd() {
      this.mainEndTime = new Date().getTime();
      if (this.mainEndTime - this.mainStartTime < 100 && !this.isBothHands && !this.isMove) {
        this.list.splice(0, this.list.length);
        return;
      }

      let scale = this.list[this.index].scale;
      if (scale != 1) {
        // 缩放倍数小于1恢复1倍数并且位置回滚当前
        this.list[this.index].scale = scale < 1 ? 1 : scale;
        const childStyle = this.$refs.childBox[this.index].style;
        if (this.list[this.index].scale == 1) {
          childStyle.setProperty('--scale', 1);
          this.setArgs(childStyle, 500, 0, 0);
          this.list[this.index].left = 0;
          this.list[this.index].top = 0;
        }
        let left = childStyle.getPropertyValue('--left');
        let top = childStyle.getPropertyValue('--top');
        // 放大过处理
        if (scale > 1) {
          childStyle.setProperty('--duration', 500);
          if (left > this.getMaxLeft()) {
            childStyle.setProperty('--left', this.getMaxLeft());
          } else if (left < -(this.getMaxLeft())) {
            childStyle.setProperty('--left', -(this.getMaxLeft()));
          }
          if (top > this.getMaxTop()) {
            childStyle.setProperty('--top', this.getMaxTop());
          } else if (top < -(this.getMaxTop())) {
            childStyle.setProperty('--top', -(this.getMaxTop()));
          }
        }

        left = childStyle.getPropertyValue('--left');
        top = childStyle.getPropertyValue('--top');
        if (!isNaN(parseFloat(left))) {
          this.list[this.index].left = parseFloat(left);
        }
        if (!isNaN(parseFloat(top))) {
          this.list[this.index].top = parseFloat(top);
        }
        this.reset();
        return;
      } else if (scale == 1 && this.computedMax()) {
        // 长图且未放大处理
        const childStyle = this.$refs.childBox[this.index].style;
        childStyle.setProperty('--duration', 500);
        let top = childStyle.getPropertyValue('--top');
        if (top > this.getMaxTop()) {
          childStyle.setProperty('--top', this.getMaxTop());
        } else if (top < -(this.getMaxTop())) {
          childStyle.setProperty('--top', -(this.getMaxTop()));
        }
        top = childStyle.getPropertyValue('--top');
        if (!isNaN(parseFloat(top))) {
          this.list[this.index].top = parseFloat(top);
        }
        this.reset();
        return;
      }
      this.reset();
    }
    ,
    // 归位
    reset() {
      const domStyle = this.$refs.preview_main.style;
      domStyle.setProperty('--duration', 500);
      let left = domStyle.getPropertyValue('--left');
      left = Math.abs(parseFloat(left));
      const distance = Math.abs(left - this.index * this.windowWidth);
      // 右滑动
      if (this.mainStartX - this.mainMoveX >= 0 && distance >= this.windowWidth / 3) {
        if (this.index >= this.list.length - 1) {
          domStyle.setProperty('--left', this.index * -this.windowWidth)
        } else {
          domStyle.setProperty('--left', (this.index + 1) * -this.windowWidth)
        }
      } else if (this.mainStartX - this.mainMoveX <= 0 && distance >= this.windowWidth / 3) {
        // 左滑动
        if (this.index <= 0) {
          domStyle.setProperty('--left', 0)
        } else {
          domStyle.setProperty('--left', (this.index - 1) * -this.windowWidth)
        }
      } else if (distance < this.windowWidth / 3) {
        domStyle.setProperty('--left', this.index * -this.windowWidth)
      }

      //储存index
      left = domStyle.getPropertyValue('--left');
      left = Math.abs(parseFloat(left));
      this.index = Math.floor(left / this.windowWidth);


      // 重置左右的元素参数
      if (this.list.length == 1 && this.list[this.index].scale == 1) {
        let childStyle = this.$refs.childBox[this.index].style;
        this.list[this.index].left = 0;
        this.list[this.index].top = 0;
        this.setArgs(childStyle, 500, 0, 0);
        return;
      }
      if (this.index - 1 >= 0 && this.list[this.index - 1].scale != 1) {
        let childStyle = this.$refs.childBox[this.index - 1].style;
        this.list[this.index - 1].scale = 1;
        this.list[this.index - 1].left = 0;
        this.list[this.index - 1].top = 0;
        this.setArgs(childStyle, 500, 0, 0);
        childStyle.setProperty("--scale", 1);
      }
      if (this.index + 1 <= this.list.length - 1 && this.list[this.index + 1].scale != 1) {
        let childStyle = this.$refs.childBox[this.index + 1].style;
        this.list[this.index + 1].scale = 1;
        this.list[this.index + 1].left = 0;
        this.list[this.index + 1].top = 0;
        this.setArgs(childStyle, 500, 0, 0);
        childStyle.setProperty("--scale", 1);
      }
    },
    // 上下滑动处理
    topOrDownMove(dom) {
      if (this.mainStartY > this.mainMoveY) {
        //上滑动
        let top = this.list[this.index].top - Math.abs(this.mainStartY - this.mainMoveY);
        dom.setProperty("--top", top)
      } else {
        let top = this.list[this.index].top + Math.abs(this.mainStartY - this.mainMoveY);
        dom.setProperty("--top", top)
      }
    },
    // 左右滑动处理
    leftOrRightMove(dom, mainDom) {
      let moveDistance = Math.abs(this.mainStartX - this.mainMoveX);
      if (this.mainStartX > this.mainMoveX) {
        //左滑动
        let left = this.list[this.index].left - moveDistance;
        if (Math.abs(left) >= this.getMaxLeft()) {
          mainDom.setProperty('--left', this.mainLeft + this.mainMoveX - this.mainStartX + Math.abs(this.moveDistanceLeft));
          return;
        }
        if (Math.abs(left) < this.getMaxLeft()) {
          this.moveDistanceLeft = moveDistance;
          dom.setProperty("--left", left);
        }
      } else {
        let left = this.list[this.index].left + moveDistance;
        if (-Math.abs(left) <= -this.getMaxLeft()) {
          mainDom.setProperty('--left', this.mainLeft + this.mainMoveX - this.mainStartX - Math.abs(this.moveDistanceLeft));
          return;
        }
        if (-(left) > -(this.getMaxLeft())) {
          this.moveDistanceLeft = moveDistance;
          dom.setProperty("--left", left);
        }
      }
    },
    // 设置 duration,left,top 参数
    setArgs(dom, duration, left, top) {
      dom.setProperty("--duration", duration);
      dom.setProperty("--left", left);
      dom.setProperty("--top", top);
    },
    //  利用三角函数，计算出两个手指的距离，即不管两个手指怎么放，都会构成一个直角三角形
    getLength(x, y, x1, y1) {
      //如果x或y相等，直接计算平行线的距离
      if (x == x1) {
        return Math.abs(x - x1)
      }
      if (y == y1) {
        return Math.abs(y - y1)
      }
      //  AB边长
      let edgeA = Math.abs(x - x1);
      let edgeB = Math.abs(y - y1);
      // 根据直角三角形的斜边长公式：c=Math.sqrt(a*a+b*b)
      return Math.sqrt(edgeA * edgeA + edgeB * edgeB);
    },
    //  计算边缘值，即图片滑动的最大距离
    getMaxLeft() {
      const childDom = this.$refs.childBox[this.index];
      let scale = this.list[this.index].scale;
      let width = childDom.offsetWidth;
      return width / 2 * scale - width / 2;
    },
    getMaxTop() {
      const childDom = this.$refs.childBox[this.index];
      let scale = this.list[this.index].scale;
      let height = childDom.offsetHeight;
      let imgHeight = childDom.childNodes[0].offsetHeight;
      let gap = (childDom.offsetHeight - imgHeight) / 2 * scale;//计算图片放大后未满屏的空隙
      gap = imgHeight * scale < height ? gap - (height - imgHeight * scale) / 2 : gap;//放大后高度未满屏时居中
      return height / 2 * scale - height / 2 - gap;
    },
    //  计算图片放大后是否满屏或是否为长图
    computedMax() {
      const dom = this.$refs.childBox[this.index];
      let height = dom.childNodes[0].offsetHeight * this.list[this.index].scale;
      if (height > dom.offsetHeight) return true;
      return false;
    },
  },
  watch: {
    current(newValue) {
      this.index = newValue
    },
    urls(newArr) {
      const THAT = this;
      THAT.list = [];
      newArr.forEach(item => {
        THAT.list.push({
          load: false,
          url: item,
          left: 0,
          top: 0,
          scale: 1
        });
      });
      this.$nextTick(() => {
        const domStyle = this.$refs.preview_main.style;
        domStyle.setProperty('--left', this.index * -this.windowWidth)
      })
    },
    // 监听双指操作
    touchMoveEdge(nowValue, oldValue) {
      if (nowValue == 0) return;
      const domStyle = this.$refs.childBox[this.index].style;
      if (nowValue > oldValue) {
        //  放大
        if (this.list[this.index].scale >= this.maxMultiple) {
          this.list[this.index].scale = this.maxMultiple;
          domStyle.setProperty("--scale", this.list[this.index].scale);
          return;
        }
        this.list[this.index].scale += 0.03;
        domStyle.setProperty("--scale", this.list[this.index].scale);
        return;
      }
      //  缩小
      if (this.list[this.index].scale <= this.minMultiple) {
        this.list[this.index].scale = this.minMultiple;
        domStyle.setProperty("--scale", this.list[this.index].scale);
        return;
      }
      this.list[this.index].scale -= 0.03;
      domStyle.setProperty("--scale", this.list[this.index].scale);
    }
  }
}
</script>

<style lang="css" scoped>
/* 样式用@import的方式引入，避免rem转换 */
@import "./imagePreview.css";
</style>